package com.changsideal.excel.util.bean;

import com.changsideal.excel.annotation.Column;
import com.changsideal.excel.annotation.Table;
import com.changsideal.excel.util.ExcelBasicTool;
import com.changsideal.exception.ExcelToolException;
import com.changsideal.tool.BasicTool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * @ClassName ExcelToBeanUtil
 * @Description 集成Excel操作工具及Excel转bean主要逻辑处理类
 * @Author Create by ChanSIdeal.HaoSc
 * @Date 2019/7/5 14:57
 * @Version 1.0
 **/
@Slf4j
public final class ExcelToBeanUtil<T> extends ExcelBasicTool implements IExcelToBeanOpera<T> {

    public ExcelToBeanUtil(Workbook workbook) {
        super(workbook);
    }

    @Override
    public List<T> invocationListBean(Class<T> workClass) {
        init();
        if (BasicTool.checkOrNull(workClass)) {
            throw new ExcelToolException("NULL EXCEPTION");
        }
        List<T> resultList = new ArrayList<>(getRowCount(0) - 1);
        try {
            List<List<String>> excelContent = read();
            Field[] declaredFields = workClass.getDeclaredFields();
            Map<Integer, Field> fieldMap = new HashMap<>(declaredFields.length);
            int index = 0;
            if (declaredFields.length > 0) {
                for (Field field : declaredFields) {
                    // 只取对象私有成员，并且含有列指定注解
                    if (Modifier.isPrivate(field.getModifiers()) &&
                            field.getAnnotation(Column.class) != null &&
                            field.getAnnotation(Column.class).importFlag()) {
                        fieldMap.put(index, field);
                    }
                    index++;
                }

                // 处理表格每行的内容注入对象, 去除标题行
                for (int inx = 1, len = excelContent.size(); inx < len; inx++) {
                    // 此处相当于new 了一个传入类型的实例,类加载器直接加载实例
                    T ts = workClass.newInstance();
                    // 遍历Excel每行数据的每列映射赋值到传入bean对应的属性中
                    for (int i = 0, other = excelContent.get(inx).size(); i < other; i++) {
                        if (fieldMap.get(i) != null) {
                            // 获取每行属性
                            Field thisField = fieldMap.get(i);
                            // 获取每行的对应的bean属性顺序
                            thisField.setAccessible(true);
                            thisField.set(ts, BasicTool.changeType(thisField.getGenericType().getTypeName(), excelContent.get(inx).get(i)));
                        }
                    }
                    resultList.add(ts);
                }
            }
        } catch (InstantiationException | IllegalAccessException | ExcelToolException e) {
            e.printStackTrace();
            log.error("转换异常");
        }
        return resultList;
    }

    public T invocationFirstBean(Class<T> workClass) {
        return invocationOneBean(workClass, 1);
    }

    @Override
    public T invocationOneBean(Class<T> workClass, Integer rowCount) {
        init();
        if (BasicTool.checkOrNull(workClass) || BasicTool.checkOrNull(rowCount)) {
            log.error("NULL EXCEPTION：传入参数为空！");
            throw new ExcelToolException("NULL EXCEPTION：传入参数为空！");
        }
        if (rowCount > getRowCount(0) - 1) {
            log.error("INDEX OF EXCEPTION：获取行数超过最大内容行数！");
            throw new ExcelToolException("INDEX OF EXCEPTION：获取行数超过最大内容行数！");
        }
        T resultObject = null;
        try {
            resultObject = workClass.newInstance();
            List<String> excelContent = getRowValue(0, rowCount);
            Field[] declaredFields = workClass.getDeclaredFields();
            Map<Integer, Field> fieldMap = new HashMap<>(declaredFields.length);
            int index = 0;
            if (declaredFields.length > 0) {
                for (Field field : declaredFields) {
                    // 只取对象私有成员，并且含有列指定注解
                    if (Modifier.isPrivate(field.getModifiers()) &&
                            field.getAnnotation(Column.class) != null &&
                            field.getAnnotation(Column.class).importFlag()) {
                        fieldMap.put(index, field);
                    }
                    index++;
                }

                // 遍历Excel每行数据的每列映射赋值到传入bean对应的属性中
                Field takeField;
                for (int i = 0, other = excelContent.size(); i < other; i++) {
                    if ((takeField = fieldMap.get(i)) != null) {
                        takeField.setAccessible(true);
                        takeField.set(resultObject, BasicTool.changeType(takeField.getGenericType().getTypeName(), excelContent.get(i)));
                    }
                }
            }
        } catch (ExcelToolException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
            log.error("转换异常");
        }
        return resultObject;
    }

    @Override
    public Map<String, T> invocationToMapBean(Class<T> workClass, Boolean order) {
        List<T> list = invocationListBean(workClass);
        Map<String, T> resultMap;
        if (order == null || !order) {
            resultMap = new HashMap<>(list.size());
        } else {
            resultMap = new LinkedHashMap<>(list.size());
        }

        for (int i = 1, len = list.size(); i <= len; i++) {
            resultMap.put(BasicTool.entrySecret(i), list.get(i));
        }
        return resultMap;
    }

    @Override
    public Set<T> invocationToSetBean(Class<T> workClass) {
        HashSet<T> resultSet = new HashSet<>(getRowCount(0) - 1);
        resultSet.addAll(invocationListBean(workClass));
        return resultSet;
    }

    public Map<String, T> invocationToMapBean(Class<T> workClass) {
        return invocationToMapBean(workClass, false);
    }

    public void createSqlFile(List<T> list, Class<T> conditionClass) {
        StringBuilder sb = new StringBuilder(" insert into ");
        if (list.isEmpty()) {
            log.error("NULL EXCEPTION：传入参数为空！");
            throw new ExcelToolException("NULL EXCEPTION：传入参数为空！");
        }
        String tableName = conditionClass.getDeclaredAnnotation(Table.class).value();
        if (StringUtils.isBlank(tableName)) {
            log.warn("生成sql失败，表名未获取到");
        }
        sb.append(tableName + "(");
        sb.append(BasicTool.magicColumnOrder(conditionClass));
        sb.append(") values (");
        String sqls = sb.toString();
        for (int i = 0; i < list.size(); i++) {
            T t = list.get(i);
            t.getClass().getName();
            sqls = sqls + "每次获取值";
            // 然后把单次string写入一个指定的txt文件内，逐行写入
            // 直至写完，然后关闭文件流输出到磁盘本地
        }

        sb.append(")");


    }
}
// 根据扫描传入要转换的Bean内是否有Sheet注解来得到相关整体sheet信息
//        Sheet mySheet = workClass.getAnnotation(Sheet.class);
//        // 得到sheet名称，如不在bean内为sheet命名，则默认sheet为空
//        String sheetName = checkOrNull(mySheet) && StringUtils.isNotBlank(mySheet.value()) ? mySheet.value() : "";